package me.zhengjie.utils;


import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.compress.utils.IOUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
import java.util.zip.Deflater;

public class ZipCompressor {
    private static final int BUFFER_SIZE = 64 * 1024; // 64KB缓冲区
    private static final int COMPRESSION_LEVEL = Deflater.BEST_SPEED;
    private static final int THREAD_POOL_SIZE = Runtime.getRuntime().availableProcessors();

    public static void compressFiles(HttpServletResponse response, String zipName, List<File> files)
            throws IOException {
        response.reset();
        response.setHeader("Content-Disposition",
                "attachment;fileName=" + zipName + "_" + DateUtil.dateYYYYMMDDHHMMSS(new Date()) + ".zip");
        response.setContentType("application/octet-stream;charset=UTF-8");

        try (OutputStream out = new BufferedOutputStream(response.getOutputStream(), BUFFER_SIZE);
             ZipArchiveOutputStream zos = new ZipArchiveOutputStream(out)) {

            zos.setLevel(COMPRESSION_LEVEL);
            zos.setEncoding(StandardCharsets.UTF_8.name());

            ExecutorService executor = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
            CompletionService<Void> completionService = new ExecutorCompletionService<>(executor);

            for (File file : files) {
                completionService.submit(() -> {
                    try (InputStream in = new BufferedInputStream(new FileInputStream(file), BUFFER_SIZE)) {
                        ZipArchiveEntry entry = new ZipArchiveEntry(file.getName());
                        zos.putArchiveEntry(entry);
                        IOUtils.copy(in, zos);
                        zos.closeArchiveEntry();
                    }
                    return null;
                });
            }
            // 等待所有任务完成
            for (int i = 0; i < files.size(); i++) {
                completionService.take().get();
            }
            executor.shutdown();
        } catch (InterruptedException | ExecutionException e) {
            Thread.currentThread().interrupt();
            throw new IOException("压缩过程中断", e);
        }
    }
}

